
#include ".\directshowplayer.h"

#define DEF_VOLUME_FULL     0L
#define DEF_VOLUME_SILENCE  -10000L
#define WM_GRAPHNOTIFY		WM_USER+13

#define SAFE_RELEASE(x) { if (x==0) x->Release(); x = 0; }

CDirectShowPlayer::CDirectShowPlayer(void)
{
	// Initialize the COM library.
	hr = CoInitialize(NULL);

	mpGB = 0;
	mpMC = 0;
	mpBA = 0;
	mpBV = 0;
	mpMS = 0;
	mpMP = 0;
	mpVW = 0;
	mpEvnt = 0;
}

CDirectShowPlayer::~CDirectShowPlayer(void)
{
	SAFE_RELEASE(mpEvnt);
	SAFE_RELEASE(mpMS);
	SAFE_RELEASE(mpMP);
	SAFE_RELEASE(mpMC);
	SAFE_RELEASE(mpBA);
	SAFE_RELEASE(mpBV);
	SAFE_RELEASE(mpVW);

	SAFE_RELEASE(mpGB);
	CoUninitialize();
}


bool CDirectShowPlayer::SetOwnerWindow(HWND aHwnd)
{
	RECT rect;
	GetClientRect(aHwnd,&rect);

	mpEvnt->SetNotifyWindow((OAHWND)aHwnd,WM_GRAPHNOTIFY,0);

	if (mpVW->put_Owner((OAHWND)aHwnd) != S_OK)
	{
		return false;
	}
	
	mpVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
	mpVW->SetWindowPosition(rect.left,rect.top,rect.right,rect.bottom);

	return true;
}

bool CDirectShowPlayer::SetVideoPosition(const RECT& rect)
{
	if (mpVW->SetWindowPosition(rect.left,rect.top,rect.right,rect.bottom) != S_OK )
	{
		return false;
	}
	return true;	
}

bool CDirectShowPlayer::GetVideoSize(long *width,long *height)
{
	if (mpBV->GetVideoSize(width,height) != S_OK)
	{
		return false;
	}
	
	return true;	
}

bool CDirectShowPlayer::OpenFile(wchar_t* aFileName)
{
	hr = mpGB->RenderFile(aFileName, NULL);
	if (FAILED(hr))
	{
		return false;
	}

	mpGB->QueryInterface(IID_IMediaControl, (void **)&mpMC);
	mpGB->QueryInterface(IID_IMediaSeeking, (void **)&mpMS);
	mpGB->QueryInterface(IID_IMediaPosition, (void **)&mpMP);

	mpGB->QueryInterface(IID_IBasicAudio,(void**)&mpBA);
	mpGB->QueryInterface(IID_IBasicVideo,(void**)&mpBV);

	mpGB->QueryInterface(IID_IVideoWindow,(void **)&mpVW);

	mpGB->QueryInterface(IID_IMediaEventEx,(void**)&mpEvnt);
	return true;
}

bool CDirectShowPlayer::Close()
{
	if(mpVW)
	{
		hr = mpVW->put_Visible(OAFALSE);
		hr = mpVW->put_Owner(NULL);
	}

	if (mpEvnt)
		hr = mpEvnt->SetNotifyWindow((OAHWND)NULL, 0, 0);
	return true;
}

bool CDirectShowPlayer::Play()
{
	hr = mpMC->Run();
	if (FAILED(hr))
	{
		return false;
	}
	return true;
}

bool CDirectShowPlayer::Stop()
{
	hr = mpMC->Stop();
	if (FAILED(hr))
	{
		return false;
	}
	return true;
}

bool CDirectShowPlayer::Pause()
{
	hr = mpMC->Pause();
	if (FAILED(hr))
	{
		return false;
	}
	return true;
}

bool CDirectShowPlayer::SetMute(bool abMute)
{
	if (abMute)
	{
		mpBA->put_Volume(DEF_VOLUME_SILENCE);

	}
	else
	{
		mpBA->put_Volume(DEF_VOLUME_FULL);
	}

	return true;
}

long CDirectShowPlayer::GetVolume()
{
	long llVol;
	mpBA->get_Volume(&llVol);
	return llVol;
}

bool CDirectShowPlayer::SetVolume(long alVolume)
{
	if (mpBA->put_Volume(alVolume) == S_OK)
	{
		return true;
	}
	return false;
}

// it's seem that for some mp3 which is VBR format,it's going wrong!
int CDirectShowPlayer::GetDuration()
{
	REFTIME ltTime;

	if( mpMP->get_Duration(&ltTime) != S_OK)
	{
		return 0;
	}
	return static_cast<int>(ltTime);
}

double CDirectShowPlayer::GetCurrentPosition()
{
	REFTIME ltTime = 0;
	mpMP->get_CurrentPosition(&ltTime);
	return static_cast<double>(ltTime);
}

bool CDirectShowPlayer::SetCurrentPosition(double aPos)
{
	mpMP->put_CurrentPosition(static_cast<REFTIME>(aPos));
	return true;
}